#include "StdAfx.h"
#include "SceneManager.h"
#include "SceneNode.h"
#include "Renderer.h"

#include "Mesh.h"
#include "MeshInstance.h"
#include "MeshManager.h"

using namespace Common;
using namespace RenderSystem;

SceneManager::SceneManager(void)
	:m_pSceneRoot(NULL)
{
}

SceneManager::~SceneManager(void)
{
	if( m_pSceneRoot != NULL )
		delete m_pSceneRoot;
}

SceneNode* SceneManager::GetRootNode( void )
{
	if( m_pSceneRoot == NULL )
		m_pSceneRoot = this->_CreateSceneNodeImpl();

	return m_pSceneRoot;
}

SceneNode* SceneManager::_CreateSceneNodeImpl(void)
{
	return new SceneNode(this);
}

void SceneManager::RenderScene( void )
{
	this->_UpdateSceneGraph();

	this->_FindVisibleObjects();

	//apply render command
	m_pDestRenderSystem->DrawScene();
}

void SceneManager::_UpdateSceneGraph( void )
{
}

void SceneManager::_FindVisibleObjects( void )
{
	SceneNode* pRoot = this->GetRootNode();
	if( pRoot == NULL )
		return;
	pRoot->FindVisibleObjects( m_pCurCameras, m_pDestRenderSystem );
}

Instance* SceneManager::_CreateInstance( const String& strMovableType, const String& strResId )
{
	ResManagersIterator itrResMgr = m_conResManagers.begin();
	for( ; itrResMgr != m_conResManagers.end(); ++itrResMgr )
	{
		if( (*itrResMgr)->GetResType() != strMovableType )
			continue;

		Resource* pResource = (*itrResMgr)->Create( strResId );
		if( pResource == NULL )
			 continue;

		//generate a id
		int iInstanceCount = pResource->GetInstanceNum();
		std::stringstream ss;
		ss << strResId << "_" << iInstanceCount;
		return pResource->CreateInstance( ss.str() );
	}
	return NULL;
}

void SceneManager::RegisterResManager( ResManager* pResMgr )
{
	for( ResManagersIterator itrResMgr = m_conResManagers.begin(); itrResMgr != m_conResManagers.end(); ++itrResMgr )
	{
		if( (*itrResMgr)->GetResType() == pResMgr->GetResType() )
			return;
	}

	m_conResManagers.push_back( pResMgr );
}

void SceneManager::UnregisterResManager( ResManager* pResMgr )
{
	for( ResManagersIterator itrResMgr = m_conResManagers.begin(); itrResMgr != m_conResManagers.end(); ++itrResMgr )
	{
		if( (*itrResMgr)->GetResType() != pResMgr->GetResType() )
			continue;

		m_conResManagers.erase( itrResMgr );
		return;
	}
}

void SceneManager::UnregisterAllResManager( void )
{
	m_conResManagers.clear();
}

MeshInstance* SceneManager::CreateMeshInstance( const String& rMeshId )
{
	return static_cast<MeshInstance*>( this->_CreateInstance("Mesh", rMeshId ) );
}
